package models

import (
	"bigdevops/src/common"
	"fmt"
	"gorm.io/gorm"
	"gorm.io/gorm/clause"
)

// 发布阶段
type CicdDeployStageStatus struct {
	Model                  // 不用每次写ID 和 createAt了
	Name            string `json:"name" validate:"required,min=1,max=200" gorm:"uniqueIndex:name_cicd_work_order_id;type:varchar(100);comment:k8s英文集群名称，支持使用通配符*进行模糊搜索" `
	Cluster         string `json:"cluster"`
	K8sAppId        uint   `json:"k8SAppId"`
	Replicas        int    `json:"replicas" `
	CicdWorkOrderId uint   `json:"cicdWorkOrderId" gorm:"uniqueIndex:name_cicd_work_order_id;comment:每一个发布工单里面的阶段是不能重复的"`

	Status       string `json:"status"  gorm:"comment:当前状态"`
	DeployStatus string `json:"deployStatus"  gorm:"comment:发布结果"`
	TestStatus   string `json:"testStatus"  gorm:"comment:测试结果"`
	//StatusDeploy string `json:"statusDeploy"  gorm:"comment:部署的状态"`
	//StatusTest   string `json:"statusTest"  gorm:"comment:测试的结果"`
	// 下一位可以显示执行逻辑
	StageIndex   int    `json:"stageIndex"  gorm:"comment:排第几位"`
	StageCount   int    `json:"stageCount" gorm:"comment:一共多少个"`
	LastError    string `json:"lastError"  gorm:"comment:最近一次的错误"`
	ActionUserId uint   `json:"actionUserId" gorm:"comment:实际的执行人"`
	Finished     int    `json:"finished" gorm:"comment:是否结束 =1 结束 =2 还没有"`
	DeployTime   string `json:"deployTime" gorm:"comment:发布的时间"`
	TestTime     string `json:"testTime" gorm:"comment:测试的时间"`

	// 是否可以显示发布的按钮
	// 得通过审批 轮到这个stage了，前面的stage是否已结束
	IfShowButtonCanDeploy   bool `json:"ifShowButtonCanDeploy" gorm:"-"`
	IfShowButtonCanRollback bool `json:"ifShowButtonCanRollback" gorm:"-"`
	IfShowButtonCanTest     bool `json:"ifShowButtonCanTest" gorm:"-"`
	// 何时展示灰度：得有灰度，灰度还没结束
	IfShowButtonCanApproveRollout bool `json:"ifShowButtonCanApproveRollout" gorm:"-"`

	// 是否可以显示测试的按钮

	// 可能还会有一些关于 发布结果的字段

	// 下面是global段  gorm:"uniqueIndex:jid_hostip;"`
	// 发布人 和测试人
	UserID        uint
	TestUserID    uint
	StatusChinese string `json:"statusChinese" gorm:"-"`
	// 详情
	Detail           string         `json:"detail" gorm:"-"`
	IndexNum         string         `json:"indexNum" gorm:"-"`
	CicdWorkOrderObj *CicdWorkOrder `json:"cicdWorkOrderObj" gorm:"-"`
	RolloutMessage   string         `json:"rolloutMessage" gorm:"-"`

	K8sAppObj      *K8sApp `json:"k8SAppObj" gorm:"-"`
	CreateUserName string  `json:"createUserName" gorm:"-"`
	ActionUserName string  `json:"actionUserName" gorm:"-"`
	TestUserName   string  `json:"testUserName" gorm:"-"`
	K8sAppName     string  `json:"k8sAppName" gorm:"-"`
	NodePath       string  `json:"nodePath" gorm:"-"` // a.b.c.d
	Key            string  `json:"key" gorm:"-"`      //给前端表格
}

func (obj *CicdDeployStageStatus) Create() error {
	return Db.Create(obj).Error

}
func (obj *CicdDeployStageStatus) DeleteOne() error {

	return Db.Select(clause.Associations).Unscoped().Delete(obj).Error

}

func (obj *CicdDeployStageStatus) CreateOne() error {
	return Db.Create(obj).Error

}

func (obj *CicdDeployStageStatus) UpdateOne() error {
	return Db.Debug().Where("id = ?", obj.ID).Updates(obj).Error

}

// 0值替换 前转后
func (obj *CicdDeployStageStatus) FillDefaultData() (err error) {
	return err
}

func (obj *CicdDeployStageStatus) FillActionUserName() error {
	if obj.ActionUserId > 0 {
		dbUser, err := GetUserById(int(obj.ActionUserId))
		if err != nil {
			return err
		}
		obj.ActionUserName = dbUser.Username
	}
	if obj.TestUserID > 0 {
		dbUser, err := GetUserById(int(obj.TestUserID))
		if err != nil {
			return err
		}
		obj.TestUserName = dbUser.Username
	}

	obj.StatusChinese = common.CicdStageStatusChineseMap[obj.Status]
	return nil
}

func (obj *CicdDeployStageStatus) FillDetail() {
	obj.Detail = fmt.Sprintf("发布时间:%v 发布人:%v 发布结果:%v\n测试时间:%v 测试人:%v 测试结果:%v",
		obj.DeployTime,
		obj.ActionUserName,
		obj.DeployStatus,
		obj.TestTime,
		obj.TestUserName,
		obj.TestStatus,
	)

}

func (obj *CicdDeployStageStatus) FillFrontAllData() (err error) {
	err = obj.FillActionUserName()
	if err != nil {
		return err
	}

	dbK8sApp, err := GetK8sAppById(int(obj.K8sAppId))
	if err != nil {
		return err
	}
	obj.K8sAppObj = dbK8sApp

	obj.K8sAppName = dbK8sApp.Name
	obj.StatusChinese = common.CicdStageStatusChineseMap[obj.Status]

	dbOrder, err := GetCicdWorkOrderById(int(obj.CicdWorkOrderId))
	if err != nil {
		return err
	}
	obj.CicdWorkOrderObj = dbOrder
	// 测试这一行的 有没有递归问题
	err = obj.CicdWorkOrderObj.FillFrontAllData()

	// 能否回滚取决于 它有没有发布成功 发布成功就让你回滚
	// 已完成回滚的不能显示按钮了
	if obj.DeployStatus == common.CICD_STAGE_DEPLOY_SUCCESS_CHINESE && obj.Status != common.CICD_STAGE_ROLLBACK_SUCCESS {
		obj.IfShowButtonCanRollback = true
	}

	// 在工单审批通过的基础上 再判断是否轮到自己了
	if obj.CicdWorkOrderObj.ApprovalStatus == common.WorkOrderInstanceStatusApprovalPass {
		// 3个条件
		// 1.下一位轮到我了
		// 2.我自身还在等待发布
		// 3.如果我不是第1为，我还需要判断前面

		//并且上一位 发布成功 我才可以发布
		if obj.CicdWorkOrderObj.CurrentStageIndex+1 == obj.StageIndex && obj.Status == common.CICD_STAGE_DEPLOY_PENDING {
			if obj.StageIndex == 1 {
				obj.IfShowButtonCanDeploy = true
			} else {
				// 获取上一位的状态
				lastStage, err := GetCicdDeployStageStatusByOrderIdAndIndex(int(obj.CicdWorkOrderObj.ID), obj.CicdWorkOrderObj.CurrentStageIndex)
				if err != nil {
					return err
				}
				if lastStage.Status == common.CICD_STAGE_TEST_SUCCESS {
					obj.IfShowButtonCanDeploy = true
				}
			}

		}
		if obj.CicdWorkOrderObj.CurrentStageIndex == obj.StageIndex && obj.Status == common.CICD_STAGE_DEPLOY_SUCCESS {
			obj.IfShowButtonCanTest = true
		}

		//if obj.Status == common.CICD_STAGE_DEPLOY_SUCCESS {
		//	obj.IfShowButtonCanTest = true
		//}

	}
	obj.FillDetail()
	return err
}

func GetCicdDeployStageStatusAll() (objs []*CicdDeployStageStatus, err error) {
	err = Db.Find(&objs).Error
	return
}

func GetCicdDeployStageStatusCount() int {
	var count int64
	Db.Table("form_designs").Count(&count)
	return int(count)
}

func GetCicdDeployStageStatusByLevel(level int) (objs []*CicdDeployStageStatus, err error) {
	err = Db.Where("level = ?", level).Preload("OpsAdmins").Find(&objs).Error
	return
}

// select * from ecs where
func GetCicdDeployStageStatusByIdsWithLimitOffset(ids []int, limit, offset int) (objs []*CicdDeployStageStatus, err error) {
	err = Db.Limit(limit).Offset(offset).Find(&objs, ids).Error
	return
}

// 查询这个节点池管理的采集Job
func GetCicdDeployStageStatusByPoolId(poolId uint) (objs []*CicdDeployStageStatus, err error) {

	err = Db.Where("enable=1 and pool_id = ?", poolId).Find(&objs).Error
	return

}

func GetCicdDeployStageStatusByOrderId(orderId int) (objs []*CicdDeployStageStatus, err error) {

	err = Db.Where("cicd_work_order_id = ?", orderId).Find(&objs).Error
	return

}

func GetCicdDeployStageStatusById(id int) (*CicdDeployStageStatus, error) {

	var dbObj CicdDeployStageStatus
	err := Db.Where("id = ?", id).First(&dbObj).Error
	if err != nil {
		if err == gorm.ErrRecordNotFound {
			return nil, fmt.Errorf("CicdDeployStageStatus不存在")
		}
		return nil, fmt.Errorf("数据库错误:%w", err)
	}
	return &dbObj, nil

}

func GetCicdDeployStageStatusByOrderIdAndIndex(orderId, index int) (*CicdDeployStageStatus, error) {

	var dbObj CicdDeployStageStatus
	err := Db.Where("cicd_work_order_id = ? and stage_index =? ", orderId, index).First(&dbObj).Error
	if err != nil {
		if err == gorm.ErrRecordNotFound {
			return nil, fmt.Errorf("CicdDeployStageStatus不存在")
		}
		return nil, fmt.Errorf("数据库错误:%w", err)
	}
	return &dbObj, nil

}

func GetCicdDeployStageStatusByName(name string) (*CicdDeployStageStatus, error) {

	var dbObj CicdDeployStageStatus
	err := Db.Where("name = ?", name).First(&dbObj).Error
	if err != nil {
		if err == gorm.ErrRecordNotFound {
			return nil, fmt.Errorf("CicdDeployStageStatus不存在")
		}
		return nil, fmt.Errorf("数据库错误:%w", err)
	}
	return &dbObj, nil

}
